package org.maven.dependencybrowser.model;
/**********************************************************************
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Contributors:

**********************************************************************/
import java.util.List;
import java.util.Stack;

public abstract class Artifact
{
    public static final String DEFAULT_SCOPE = "compile";

    private String groupId;
    private String artifactId;
    private String version;
    private String scope;

    private Artifact parent;
    private ExclusionList exclusions;
    private int selected;

    public static final int SELECTED_NONE = 0;
    public static final int SELECTED_PATH = 1;
    public static final int SELECTED_PRINCIPLE = 2;

    protected Artifact(Artifact parent, String groupId, String artifactId, String version, String scope) throws ArtifactInitialisationException
    {
        this.parent = parent;
        this.groupId = validate("GroupId", groupId);
        this.artifactId = validate("ArtifactId", artifactId);
        this.version = validate("Version", version);
        this.scope = (scope == null || scope.trim().equals("")) ? "" : scope;
        exclusions = new ExclusionList();
        selected = SELECTED_NONE;
    }

    public void addExclusion(String groupId, String artifactId)
    {
        exclusions.addExclusion(groupId, artifactId);
    }

    public boolean isExcluded(String groupId, String artifactId, Stack<Artifact> path)
    {
        if (exclusions.isExcluded(groupId, artifactId))
        {
            return true;
        }
        if (path == null)
        {
            path = new Stack<Artifact>();
        }
        // may fail on circular dependency
        if (parent != null && !path.contains(parent))
        {
            path.push(this);
            return parent.isExcluded(groupId, artifactId, path);
        }
        return false;
    }

    private String validate(String type, String value) throws ArtifactInitialisationException
    {
        if (value == null || value.trim().length() == 0)
        {
            throw new ArtifactInitialisationException(type + " is missing");
        }
        return value.trim();
    }

    public abstract boolean isLeaf();

    public abstract List getDependencies();

    public abstract int dependencyCount();

    public String getArtifactId()
    {
        return artifactId;
    }

    public String getGroupId()
    {
        return groupId;
    }

    public String getScope()
    {
        return scope;
    }

    public String getVersion()
    {
        return version;
    }

    public Artifact getParent()
    {
        return parent;
    }

    public int getSelected()
    {
        return selected;
    }

    public void select(int state)
    {
        selected = state;
        if (parent == null)
        {
            return;
        }
        if (SELECTED_NONE == state)
        {
            if (SELECTED_NONE != parent.getSelected())
            {
                parent.select(SELECTED_NONE);
            }
        }
        else
        {
            if (SELECTED_PATH != parent.getSelected())
            {
                parent.select(SELECTED_PATH);
            }
        }
    }

    public String getId()
    {
        return groupId + ":" + artifactId + ":" + version + "(" + scope + ")";
    }

    public boolean equals(Object obj)
    {
        if (obj instanceof Artifact)
        {
            Artifact compareTo = (Artifact) obj;
            if (!safeCompare(groupId, compareTo.groupId))
            {
                return false;
            }
            if (!safeCompare(artifactId, compareTo.artifactId))
            {
                return false;
            }
            if (!safeCompare(version, compareTo.version))
            {
                return false;
            }
            return true;
        }
        return false;
    }

    private boolean safeCompare(String s1, String s2)
    {
        return ((s1 == null) == (s2 == null)) && ((s1 == null || s1.equalsIgnoreCase(s2)));
    }

    public int hashCode()
    {
        return getId().hashCode();
    }

    public String toString()
    {
        return getId() + "[" + dependencyCount() + "]";
    }

}
